package org.finesys.common.excel.converter;

import cn.idev.excel.converters.Converter;
import cn.idev.excel.enums.CellDataTypeEnum;
import cn.idev.excel.metadata.GlobalConfiguration;
import cn.idev.excel.metadata.data.ReadCellData;
import cn.idev.excel.metadata.data.WriteCellData;
import cn.idev.excel.metadata.property.ExcelContentProperty;
import cn.idev.excel.util.DateUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 日期+时间 转换器
 */
public enum LocalDateTimeStringConverter implements Converter<LocalDateTime> {
    /**
     * 实例
     */
    INSTANCE;


    private static final String MINUS = "-";
    private static final String COLON = ":";
    public static final String DATE_FORMAT_21 = "yyyyMMdd HH:mm:ss.SSS";
    public static final String DATE_FORMAT_17 = "yyyyMMddHHmmssSSS";
    public static final String DATE_FORMAT_23 = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String DATE_FORMAT_23_FORWARD_SLASH = "yyyy/MM/dd HH:mm:ss.SSS";

    @Override
    public Class<?> supportJavaTypeKey() {
        return LocalDateTime.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    @Override
    public LocalDateTime convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        String pattern;
        if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
            pattern = switchDateFormat(cellData.getStringValue());
        } else {
            pattern = contentProperty.getDateTimeFormatProperty().getFormat();
        }
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
        return LocalDateTime.parse(cellData.getStringValue(), dateTimeFormatter);
    }


    @Override
    public WriteCellData<?> convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        String pattern;
        if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
            pattern = DateUtils.DATE_FORMAT_19;
        } else {
            pattern = contentProperty.getDateTimeFormatProperty().getFormat();
        }
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
        return new WriteCellData<>(value.format(dateTimeFormatter));
    }

    /**
     * 转换日期格式
     */
    private static String switchDateFormat(String dateString) {
        int length = dateString.length();
        switch (length) {
            case 23:
                if (dateString.contains(MINUS)) {
                    return DATE_FORMAT_23;
                } else {
                    return DATE_FORMAT_23_FORWARD_SLASH;
                }
            case 21:
                return DATE_FORMAT_21;
            case 19:
                if (dateString.contains(MINUS)) {
                    return DateUtils.DATE_FORMAT_19;
                } else {
                    return DateUtils.DATE_FORMAT_19_FORWARD_SLASH;
                }
            case 17:
                if (dateString.contains(COLON)) {
                    return DateUtils.DATE_FORMAT_17;
                } else {
                    return DATE_FORMAT_17;
                }
            case 14:
                return DateUtils.DATE_FORMAT_14;
            case 10:
                return DateUtils.DATE_FORMAT_10;
            default:
                throw new IllegalArgumentException("can not find date format for:" + dateString);
        }
    }

}
